local mt = ac.buff['位移']

mt.level = 1

mt.pulse = 0.03

mt.displace = true

-- 目标
mt.target = ac.point(0,0)
-- 弧度
mt.orc = 0.00
-- 追踪 （不追踪目标跑远了会停下）
mt.homing = true 
-- 速度
mt.speed = 1000
-- 加速度
mt.accele = 0

function mt:on_add()
    local unit = self.owner 
    if unit:has_restriction '禁锢' then 
        self:remove()
        return false
    end 
    local launch = unit:get_point()
    local launch_height = launch:get_height() + unit:get_height()
    local impact = self.target:get_point()
    local impact_height = impact:get_height()
    if self.target.type == 'point' then 
        impact_height = impact_height + self.target.z
    elseif self.target.type == 'unit' then 
        impact_height = impact_height + self.target:get_height()
    end 
    local distance = launch * impact    -- 水平距离
    local highest = distance * self.orc + math.lerp(launch_height, impact_height, 0.5) -- 最高点
    local length = math.sqrt((launch_height - impact_height) ^ 2 + (distance) ^ 2)  -- 总位移
    if length <= 0 then 
        self:notify("on_finish")
        self:remove()
        return 
    end 
    self.highest = highest
    self.length = length
    self.launch = launch
    self.launch_height = launch_height
    self.impact = impact
    self.impact_height = impact_height
    self.current_point = launch
    self.current_height = launch_height
    self.moved = 0
    self.progress = 0
    if self.speed < 0 then 
        self.speed = self.length / self.pulse
    elseif self.speed == 0 then 
        self.speed = self.length
    end 
    self.has_homing = self.homing
    self.has_revise = true
    self.has_finish = true  -- 派发结束事件
    self.has_resume = true
    self.has_launch = true
    self.has_unmove = true
    unit:notify("单位-打断位移", unit)
    unit:add_restriction "位移"
    unit:add_restriction "幽灵"
    if self.stun_flag then 
        unit:add_restriction "晕眩"
        self.has_stun = true
    end
    self.triggers = {}
    self.triggers[1] = unit:on "单位-打断位移" (function(_, _, flag)
        self.has_resume = (flag == true)    -- 有这个标记代表恢复默认高度
        self:notify("on_break")
        self:remove()
    end)
    if self.target.type == 'unit' and self.has_homing then  
        self.triggers[2] = self.target:on "单位-死亡" (function()
            self.has_homing = false 
        end)
    end
    self:notify("on_launch")
end

function mt:on_pulse()
    local unit = self.owner 
    local target = self.target
    local launch = self.launch
    local launch_height = self.launch_height
    local impact = self.impact
    local impact_height = self.impact_height
    local highest = self.highest
    local length = self.length
    local current_point = self.current_point
    local current_height = self.current_height
    local moved = self.moved 
    local progress = self.progress
    local speed = self.speed
    local accele = self.accele
    local pulse = self.pulse
    local orc = self.orc 

    if self.has_homing then 
        if self.has_revise then 
            local point = self.target:get_point()
            local height = point:get_height()
            if (math.sqrt((impact_height - height) ^ 2 + (impact * point) ^ 2)) <= 16 then 
                -- 进行修正
                highest = launch * point * (orc) + math.lerp(launch_height, height, 0.5)
                length = math.sqrt((launch_height - height) ^ 2 + (launch * point) ^ 2)
                impact = point
                impact_height = height
                if self.target.type == 'point' then 
                    impact_height = impact_height + self.target.z
                elseif self.target.type == 'unit' then 
                    impact_height = impact_height + self.target:get_height()
                end 
                self.highest = highest
                self.length = length 
                self.impact = impact
                self.impact_height = impact_height
            else
                self.has_revise = false
            end
        end
    end 

    if not self.has_revise then 
        impact = self.target:get_point()
        impact_height = impact:get_height()
        if self.target.type == 'point' then 
            impact_height = impact_height + self.target.z
        elseif self.target.type == 'unit' then 
            impact_height = impact_height + self.target:get_height()
        end 
    end

    if length <= 0 then
        self:notify("on_finish")
        self:remove()
        return
    end 

    speed = speed + accele * pulse
    moved = moved + speed * pulse

    if self.has_revise then 
        -- 抛物线移动
        progress = math.min(moved / length, 1)
        current_point = launch:lerp(impact, progress)
        if orc ~= 0 then 
            current_height = math.parabola(launch_height, highest, impact_height, progress)
        else 
            current_height = math.lerp(launch_height, impact_height, progress)
        end
    else 
        -- 追踪移动
        length = math.sqrt((current_height - impact_height) ^ 2 + (current_point * impact) ^ 2)
        progress = math.min((speed * pulse) / length, 1)
        current_point = current_point:lerp(impact, progress)
        current_height = math.lerp(current_height, impact_height, progress)
    end 
    if self:notify("on_move", current_point, current_height) == false then 
        self:remove()
        return 
    end 
    if self.removed then
        return
    end
    self.current_height = current_height
    self.current_point = current_point
    self.progress = progress
    self.moved = moved
    self.length = length
    self.speed = speed
    unit:set_point( current_point )
    unit:set_height( current_height - current_point:get_height() )
    if self.progress == 1 then 
        self:notify("on_finish")
        self:remove()
    end 
end

function mt:on_remove()
    local unit = self.owner 
    if self.triggers then 
        for i = 1, #self.triggers do 
            self.triggers[i]:remove()
        end
    end 
    if self.has_unmove then 
        unit:remove_restriction "位移"
        unit:remove_restriction "幽灵"
    end 
    if self.has_stun then 
        unit:remove_restriction "晕眩"
    end
    if self.has_resume then 
        unit:set_height( unit:get_default_height() )
    end 
    if self.has_launch then 
        self:notify("on_stop")
    end
end

function mt:on_cover()
    self.has_resume = false
    return true
end